
#include "hw_instance.h"
#include "base_util.h"
#include <cstdio>


HwInstance::AVBufferRefData::~AVBufferRefData()
{
    if (m_buffer_ref)
    {
        av_buffer_unref(&m_buffer_ref);
    }
}

HwInstance::HwInstance()
{

}

HwInstance::~HwInstance()
{
	PrintLogMsg("release hw instance");
    m_buffer_map.clear();
}

void HwInstance::AddBuffer(AVBufferRef *buffer)
{
	// PrintLogMsg("add new buffer ref");
	// auto * buffer_ref = av_buffer_ref(buffer);	
}

AVBufferRef * HwInstance::GetBuffer(const std::string & name)
{
    if (!name.empty())
    {
        bool result = CreateHw(name);
        if (result)
        {
            return av_buffer_ref(m_buffer_map[name]->m_buffer_ref);
        }
        return nullptr;
    }
    else
    {
        if (!m_buffer_map.empty())
        {
            return av_buffer_ref(m_buffer_map.begin()->second->m_buffer_ref);
        }
    }
    return nullptr;
}

AVBufferRef *HwInstance::GetBuffer(AVHWDeviceType hw_type)
{
    for (auto & data : m_buffer_map)
    {
        if (data.second->m_hw_type == hw_type)
        {
            return av_buffer_ref(data.second->m_buffer_ref);
            break;
        }
    }
    return nullptr;
}

AVHWDeviceType HwInstance::GetHwType(const std::string &name)
{
    CreateHw(name);
    auto iter = m_buffer_map.find(name);
    if (iter != m_buffer_map.end())
    {
        return iter->second->m_hw_type;
    }
    return AV_HWDEVICE_TYPE_NONE;
}

bool HwInstance::CreateHw(const std::string &hw_name)
{
    bool create_result = false;
    auto iter = m_buffer_map.find(hw_name);
    if (iter == m_buffer_map.begin())
    {
        auto hw_type = av_hwdevice_find_type_by_name(hw_name.c_str());
        if (hw_type != AV_HWDEVICE_TYPE_NONE)
        {
            auto data = std::make_shared<AVBufferRefData>();
            data->m_hw_type    = hw_type;
            data->m_buffer_ref = nullptr;
            data->m_index      = 0;
            int result = av_hwdevice_ctx_create(&data->m_buffer_ref, hw_type, nullptr, nullptr, 0);
            if (result < 0)
            {
                create_result = false;
                PrintLog(result);
            }
            else
            {
                create_result = true;
                m_buffer_map[hw_name] = data;
            }
        }
        else
        {
            create_result = false;
        }
    }
    else
    {
        create_result = true;
    }
	return create_result;
}
